﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Infrastructure.Data;
using AlbumDesigner.Helpers;
using Keepo.Helpers;
using AlbumDesigner.Models.Enums;

namespace Keepo.Models.Services
{
    public class AlbumsLogic
    {
        static public string Hello()
        {
            return "Test";
        }

        static public AlbumPageExport GetAlbumPageById(int pageId)
        {
            using (var db = new AlbumContext())
            {
                if (canUserEdit(AlbumPageId: pageId))
                {
                    var page = db.AlbumPages.FirstOrDefault(p => p.AlbumPageId == pageId);

                    if (page == null)
                    {
                        return null;
                    }

                    AlbumPageExport export = new AlbumPageExport(page);
                    export.PageNum = AlbumPagesHelper.PageNumByPageId(page.AlbumPageId);

                    return export;
                }
                else
                {
                    return null;
                }
            }
        }

        static public AlbumPageExport[] GetAlbumPagesBySectionId(int sectionId)
        {
            if (canUserEdit(AlbumSectionId: sectionId) || true)
            {
                using (GenericRepository repository = new GenericRepository())
                {
                    var pages = repository.Find<AlbumPage>(m => m.AlbumSectionId == sectionId);
                    AlbumPageExport[] exportPages = pages.Select(page => new AlbumPageExport(page)).OrderBy(p => p.SectionPageIdx).ToArray();

                    int pageNum = AlbumPagesHelper.SectionFirstPageNum(sectionId);

                    // Add Numbers to pages
                    foreach (var page in exportPages)
                    {
                        page.PageNum = pageNum;
                        pageNum += page.IsSingle ? 1 : 2;
                    }

                    return exportPages;
                }
            }
            return null;
        }

        static public AlbumPageExport[] GetAlbumPagesByAlbumId(int albumId)
        {
            if (canUserEdit(albumId) || true)
            {
                using (var db = new AlbumContext())
                {
                    var sectionIds = db.AlbumSections.Where(m => m.AlbumId == albumId).OrderBy(m => m.SectionIdx).Select(m => m.AlbumSectionId).ToArray();

                    List<AlbumPageExport> albumPages = new List<AlbumPageExport>();

                    foreach (var sectionId in sectionIds)
                    {
                        var temp = GetAlbumPagesBySectionId(sectionId);
                        albumPages.AddRange(temp);
                    }

                    return albumPages.ToArray();
                }
            }
            return null;
        }

        static public bool MoveAlbumPageById(int srcPageId, int dstPageId)
        {
            return AlbumPagesHelper.MoveAlbumPage(srcPageId, dstPageId);
        }

        static public bool MoveAlbumPageByIdx(int sectionId, int srcPageIdx, int dstPageIdx)
        {
            using (GenericRepository repository = new GenericRepository())
            {
                var srcPage = repository.FindOne<AlbumPage>(p => p.AlbumSectionId == sectionId && p.SectionPageIdx == srcPageIdx);
                var dstPage = repository.FindOne<AlbumPage>(p => p.AlbumSectionId == sectionId && p.SectionPageIdx == dstPageIdx);

                if (srcPage == null || dstPage == null)
                {
                    return false;
                }
                else
                {
                    return AlbumPagesHelper.MoveAlbumPage(srcPage.AlbumPageId, dstPage.AlbumPageId);
                }
            }
        }

        static public bool HasThumbnail(int pageId, bool val)
        {
            using (GenericRepository repository = new GenericRepository())
            {
                var page = repository.GetByKey<AlbumPage>(pageId);

                if (page == null)
                {
                    return false;
                }

                page.HasThumbnail = val;
                repository.UnitOfWork.SaveChanges();
                return true;
            }
        }

        static public bool SetHasXml(int pageId, bool val)
        {
            using (GenericRepository repository = new GenericRepository())
            {
                var page = repository.GetByKey<AlbumPage>(pageId);

                if (page == null)
                {
                    return false;
                }

                page.HasXml = val;
                page.ModifiedDate = DateTime.Now;
                repository.UnitOfWork.SaveChanges();
                
                return true;
            }
        }

        static public bool SetHasRender(int pageId, bool val)
        {
            using (GenericRepository repository = new GenericRepository())
            {
                var page = repository.GetByKey<AlbumPage>(pageId);

                if (page == null)
                {
                    return false;
                }

                if (page.HasRender != val)
                {
                    page.HasRender = val;
                    repository.UnitOfWork.SaveChanges();
                }
                return true;
            }
        }

        // Section names to show in Image gallery
        // Logic:
        // 1. If no sectionId, the return all sections
        // 2. If there is sectionId
        //  2.1 In case it's a class, show only the class' category and the album
        //  2.2 In case it's not a class, show all sections
 
        static public Dictionary<string, object>[] getAlbumSectionNames(int albumId, int sectionId = -1)
        {
            List<AlbumSection> sections = null;

            using (AlbumContext db = new AlbumContext())
            {
                List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();

                if (sectionId != -1)
                {
                    var section = db.AlbumSections.Find(sectionId);
                    
                    if (section != null && section.isClassSection())
                    {
                        sections = new List<AlbumSection>();
                        sections.Add(section);
                    }
                }
                
                if(sections == null)
                {
                    sections = db.AlbumSections.Where(s => s.AlbumId == albumId).ToList();
                }

                foreach (var section in sections)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();

                    dic["key"] = section.AlbumSectionId;
                    dic["english"] = section.Title;
                    // dic["hebrew"] = section.TitleHebrew;

                    list.Add(dic);
                }

                return list.ToArray();
            }
        }

        static public DesignImageExport[] getGeneralImages()
        {
            using (var db = new AlbumContext())
            {
                var designImages = db.AlbumImages.Where(i => i.AlbumId == null);
                return designImages.ToArray().Select(image => new DesignImageExport(image)).ToArray();
            }
        }

        static public DesignImageExport[] getImagesByAlbumId(int albumId)
        {
            using (var db = new AlbumContext())
            {
                var designImages = db.AlbumImages.Where(i => i.AlbumId == albumId && i.AlbumSectionId == null && !i.IsRemoved);
                return designImages.ToArray().Select(image => new DesignImageExport(image)).ToArray();
            }
        }

        static public DesignImageExport[] getImagesBySectionId(int sectionId)
        {
            using (var db = new AlbumContext())
            {
                var designImages = db.AlbumImages.Where(i => i.AlbumSectionId == sectionId && !i.IsRemoved);
                return designImages.ToArray().Select(image => new DesignImageExport(image)).ToArray();
            }
        }

        public static bool canUserEdit(int AlbumId = -1, int AlbumSectionId = -1, int AlbumPageId = -1)
        {
            if (HttpContext.Current.Request.Url.ToString().Contains("localhost"))
            {
               // return true;
            }

            bool canUserEdit = false;

            using (var db = new AlbumContext())
            {
                if (UserHelper.IsLogon())
                {
                    var user = UserHelper.CurrentUser();
                    var userId = user.UserId;

                    //check if the login user is Admin/Studio/Sales/Photographer
                    if (user.UserPermissionId != (int)AlbumUsers.Client)
                    {
                        canUserEdit = true;
                    }
                    else
                    {
                        if (AlbumPageId != -1)
                        {
                            var albumPage = db.AlbumPages.Find(AlbumPageId);

                            if (albumPage != null)
                            {
                                canUserEdit = albumPage.AlbumSection.EditorId == userId ||
                                    albumPage.AlbumSection.Album.EditorId == userId;
                            }
                        }

                        //if there is albumSection specified
                        else if (AlbumSectionId != -1)
                        {
                            //check if album section editor
                            var albumSection = db.AlbumSections.Find(AlbumSectionId);
                            if (albumSection != null)
                            {
                                canUserEdit = albumSection.EditorId == userId ||
                                    albumSection.Album.EditorId == userId;
                            }
                        }

                        //if there is album specified
                        else if (AlbumId != -1)
                        {
                            //check if album editor
                            var album = db.Albums.Find(AlbumId);
                            if (album != null)
                            {
                                canUserEdit = album.EditorId == userId;
                            }
                        }
                        
                    }
                }

                return canUserEdit;
            }
        }

        static public Dictionary<string, object>[] getBackgroundCategories()
        {
            using (AlbumContext db = new AlbumContext())
            {
                List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();

                foreach (var category in db.ImageCategories)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();

                    dic["key"] = category.ImageCategoryId;
                    dic["english"] = category.Title;
                    dic["hebrew"] = category.TitleHebrew;

                    list.Add(dic);
                }

                return list.ToArray();
            }
        }

        static public DesignImageExport[] getBackgroundImagesByCategoryId(int categoryId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var images = db.BackgroundImages.Where(m => m.ImageCategoryId == categoryId);
                return images.ToArray().Select(m => m.export()).ToArray();
            }
        }

        static public Dictionary<string, object>[] getLayoutCategories()
        {
            using (AlbumContext db = new AlbumContext())
            {
                List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();

                foreach (var category in db.LayoutCategories)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();

                    dic["key"] = category.LayoutCategoryId;
                    dic["english"] = category.Title;
                    dic["hebrew"] = category.TitleHebrew;

                    list.Add(dic);
                }

                return list.ToArray();
            }
        }

        static public PageLayoutExport[] getPageLayoutsByCategoryId(int categoryId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var layouts = db.PageLayouts.Where(m => m.LayoutCategoryId == categoryId).ToArray().Select(m => new PageLayoutExport(m)).ToArray();
                return layouts;
            }
        }

        static public PageLayoutExport[] getPageLayoutsByAlbumId(int albumId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var layouts = db.PageLayouts.Where(m => m.AlbumId == albumId).ToArray().Select(m => new PageLayoutExport(m)).ToArray();
                return layouts;
            }
        }

        static public bool addPageLayout(PageLayoutExport pageLayout)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var layout = pageLayout.toEntity();

                // If not asoociated with album
                if (pageLayout.AlbumId == -1)
                {
                    layout.AlbumId = null;
                    layout.LayoutCategoryId = 1;
                }
                

                db.PageLayouts.Add(layout);
                db.SaveChanges();
            }

            return true;
        }

        static public bool removePageLayout(int pageLayoutId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var layout = db.PageLayouts.Find(pageLayoutId);

                // If not asoociated with album
                if (layout!=null && layout.Album!=null)
                {
                    db.PageLayouts.Remove(layout);
                    db.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        static public void setImagePagePairs(int pageId, int[] imageIds)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var albumPage = db.AlbumPages.Find(pageId);

                if (albumPage != null)
                {
                    db.ImagePagePairs.Where(m => m.AlbumPageId == pageId).ToList().ForEach(t => db.ImagePagePairs.Remove(t));
                    db.SaveChanges();

                    imageIds.ToList().ForEach(id => db.ImagePagePairs.Add(new ImagePagePair() { AlbumPageId = pageId, AlbumImageId = id }));
                    db.SaveChanges();
                }
            }
        }

        // For entire album except pageId
        static public int[] getImagePagePairs(int pageId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var page = db.AlbumPages.Find(pageId);

                var ids = db.ImagePagePairs.Where(m => m.AlbumPage.AlbumSection.AlbumId == page.AlbumSection.AlbumId
                    && m.AlbumPageId != pageId).Select(t => t.AlbumImageId).ToArray();

                return ids;
            }
        }

        static public DesignMaskExport[] getDesignMasks(int albumId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                if (albumId == -1)
                {
                    return db.DesignMasks.Where(m => m.AlbumId == null).OrderBy(m => m.Title).ToArray().Select(m => new DesignMaskExport(m)).ToArray();
                }
                else
                {
                    return db.DesignMasks.Where(m => m.AlbumId == albumId).ToArray().Select(m => new DesignMaskExport(m)).ToArray();
                }
            }
        }

        static public bool addDesignMask(DesignMaskExport designMask)
        {
            using (AlbumContext db = new AlbumContext())
            {
                db.DesignMasks.Add(designMask.toEntity());
                db.SaveChanges();

                return true;
            }
        }

        static public AlbumDetailsExport getAlbumDetails(int albumId, int sectionId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var album = db.Albums.Find(albumId);
                var section = db.AlbumSections.Find(sectionId);

                if (album != null)
                {
                    var export = new AlbumDetailsExport(album);

                    if (section != null)
                    {
                        export.SectionName = section.Title;
                    }

                    return export;

                }
                else
                {
                    return null;
                }

            }
        }


        // Premade Pages
        static public Dictionary<string, object>[] getPremadePageCategories()
        {
            using (AlbumContext db = new AlbumContext())
            {
                List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();

                foreach (var category in db.PremadePageCategories)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();

                    dic["key"] = category.PremadePageCategoryId;
                    dic["english"] = category.Title;
                    dic["hebrew"] = category.TitleHebrew;

                    list.Add(dic);
                }

                return list.ToArray();
            }
        }

        static public AlbumPageExport getPremadePageById(int premadePageId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var premadePage = db.PremadePages.Find(premadePageId);
                return (premadePage != null) ? new AlbumPageExport(premadePage) : null;
            }
        }

        static public bool setPremadePageSaved(int pageId)
        {
            using (AlbumContext db = new AlbumContext())
            {
                var page = db.PremadePages.Find(pageId);

                if (page == null)
                {
                    return false;
                }

                page.HasXml = true;
                page.HasThumbnail = true;
                page.ModifiedDate = DateTime.Now;
                
                db.SaveChanges();

                return true;
            }
        }

        static public AlbumPageExport[] getPremadePagesByCategoryId(int categoryId)
        {
            using (var db = new AlbumContext())
            {
                var pages = db.PremadePages.Where(m => m.PremadePageCategoryId == categoryId).ToArray();
                return pages.Select(m => new AlbumPageExport(m)).ToArray();
            }
        }

        static public string getNotesForPage(int pageId)
        {
            using( var db = new AlbumContext())
            {
                var page = db.AlbumPages.Find(pageId);
                return page == null ? "" : page.Notes;
            }
        }

        static public bool setNotesForPage(int pageId, string notes)
        {
            using (var db = new AlbumContext())
            {
                var page = db.AlbumPages.Find(pageId);

                if (page != null)
                {
                    page.Notes = notes;
                    db.SaveChanges();
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        static public string[] getDesignTips()
        {
            using (var db = new AlbumContext())
            {
                return db.Tips.Select(t => t.TipText).ToArray();
            }
        }

    }
}